{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import io\n",
    "import panel as pn\n",
    "pn.extension()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``FileInput`` widget allows uploading one or more files from the frontend and makes the filename, file data and [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) available in Python. To upload large files, use the [`FileDropper`](FileDropper.ipynb) widget.\n",
    "\n",
    "Discover more on using widgets to add interactivity to your applications in the [how-to guides on interactivity](../../how_to/interactivity/index.md). Alternatively, learn [how to set up callbacks and (JS-)links between parameters](../../how_to/links/index.md) or [how to use them as part of declarative UIs with Param](../../how_to/param/index.md).\n",
    "\n",
    "#### Parameters:\n",
    "\n",
    "For details on other options for customizing the component see the [layout](../../how_to/layout/index.md) and [styling](../../how_to/styling/index.md) how-to guides.\n",
    "\n",
    "##### Core\n",
    "\n",
    "* **``accept``** (str):  A list of file input filters that restrict what files the user can pick from\n",
    "* **``directory``** (str): If directories is upload instead of files\n",
    "* **``filename``** (str/list): The filename(s) of the uploaded file(s)\n",
    "* **``mime_type``** (str/list): The mime type(s) of the uploaded file(s)\n",
    "* **``multiple``** (boolean): Whether to allow uploading multiple files\n",
    "* **``value``** (bytes/list): A bytes object containing the file data or if `multiple` is set a list of bytes objects.\n",
    "\n",
    "___"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_input = pn.widgets.FileInput()\n",
    "\n",
    "file_input"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To read out the content of the file you can access the ``value`` parameter, which holds a [bytestring](https://docs.python.org/3/library/stdtypes.html#bytes-objects) containing the file's contents. Additionally information about the file type is made available on the ``filetype`` parameter expressed as a MIME type, e.g. ``image/png`` or ``text/csv``."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_input.value"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The widget also has a ``save`` method that allows saving the uploaded data to a file or [BytesIO](https://docs.python.org/3/library/io.html#binary-i-o) object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# File\n",
    "if file_input.value is not None:\n",
    "    file_input.save('test.png')\n",
    "\n",
    "# BytesIO object\n",
    "if file_input.value is not None:\n",
    "    out = io.BytesIO()\n",
    "    file_input.save(out)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `accept` parameter restricts what files the user can pick from. This consists of comma-separated list of standard HTML\n",
    "file input filters. Values can be:\n",
    "\n",
    "* `<file extension>` - Specific file extension(s) (e.g: .gif, .jpg, .png, .doc) are pickable\n",
    "* `audio/*` - all sound files are pickable\n",
    "* `video/*` - all video files are pickable\n",
    "* `image/*` - all image files are pickable\n",
    "* `<media type>` - A valid [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml), with no parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_input = pn.widgets.FileInput(accept='.csv,.json')\n",
    "\n",
    "file_input"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To allow uploading multiple files we can also set `multiple=True` or if you want to upload a whole directory `directory=True`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_input = pn.widgets.FileInput(accept='.png', multiple=True)\n",
    "\n",
    "file_input"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When uploading one or more files the `filename`, `mime_type` and `value` parameters will now be lists. \n",
    "\n",
    "You can also clear the file input with the `.clear()` method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "file_input.clear()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Upload size limits\n",
    "\n",
    "While the `FileInput` widget doesn't set any limit on the size of a file that can be selected by a user, the infrastructure onto which Panel relies (web browsers, Bokeh, Tornado, notebooks, kubernetes etc.) limits significantly what is actually possible. By default the `FileInput` widget allows to upload data that is in the order of 10 MB. To increase these limits see the [Websocket Configuration Guide](../../how_to/server/websockets.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Controls\n",
    "\n",
    "The `FileInput` widget exposes a number of options which can be changed from both Python and Javascript. Try out the effect of these parameters interactively:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pn.Row(file_input.controls(jslink=True), file_input)"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
